#include "main.h"

#define SUB1G_WR_CMD (unsigned char)0x80
#define SUB1G_RD_CMD (unsigned char)0xC0

#define SCK_Pin GPIO_PIN_2
#define SCK_GPIO_Port GPIOB
#define SDA_Pin GPIO_PIN_1
#define SDA_GPIO_Port GPIOB
#define LED_Pin GPIO_PIN_7
#define LED_GPIO_Port GPIOA
#define K1_Pin GPIO_PIN_4
#define K1_GPIO_Port GPIOB
#define K2_Pin GPIO_PIN_3
#define K2_GPIO_Port GPIOB

unsigned short CfgTbl_433[21] =
    {
        0x007F,
        0x5400,
        0x0000,
        0x0000,
        0x0000,
        0xF000,
        0x0000,
        0xC0FC,
        0x4208,
        0x0160,
        0x2401,
        0x0081,
        0x8000,
        0x0000,
        0xFFFF,
        0x0020,
        0x5FD9,
        0xA2D6,
        0x0E13,
        0x0019,
        0x0000};

unsigned short CfgTbl_315[21] =
    {
        0x007F,
        0x5400,
        0x0000,
        0x0000,
        0x0000,
        0xF000,
        0x0001,
        0xCEC4,
        0x4808,
        0x0211,
        0x2401,
        0x0081,
        0x8000,
        0x0000,
        0xFFFF,
        0x0020,
        0x5FD2,
        0xA2D6,
        0x0E13,
        0x0019,
        0x0000};

static unsigned char send_data[8] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF};

static void delay10Us(unsigned int d10UsCnt)
{
    // delay 10us at Mcu Clock as 24M
    unsigned char nTick; // 5:3.7us; 10:6.2us; 20:9.2; 22:10us
    while (d10UsCnt--)
    {
        nTick = 25;
        while (nTick--)
            ;
    }
}

static void TWI_SDA_H(void)
{
    HAL_GPIO_WritePin(SDA_GPIO_Port, SDA_Pin, GPIO_PIN_SET);
}

static void TWI_SDA_L(void)
{
    HAL_GPIO_WritePin(SDA_GPIO_Port, SDA_Pin, GPIO_PIN_RESET);
}

static void TWI_SDA_PUSH_PULL(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    __HAL_RCC_GPIOB_CLK_ENABLE();

    GPIO_InitStruct.Pin = SDA_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(SDA_GPIO_Port, &GPIO_InitStruct);
}

static void TWI_SDA_OPEN_DRAIN(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    __HAL_RCC_GPIOB_CLK_ENABLE();

    GPIO_InitStruct.Pin = SDA_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(SDA_GPIO_Port, &GPIO_InitStruct);
}

static void TWI_SCK_H(void)
{
    HAL_GPIO_WritePin(SCK_GPIO_Port, SCK_Pin, GPIO_PIN_SET);
}

static void TWI_SCK_L(void)
{
    HAL_GPIO_WritePin(SCK_GPIO_Port, SCK_Pin, GPIO_PIN_RESET);
}

static unsigned char TWI_SDA_read(void)
{
    unsigned char value;
    value = HAL_GPIO_ReadPin(SDA_GPIO_Port, SDA_Pin);
    return value;
}

static void TWI_SCK_PUSH_PULL(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    __HAL_RCC_GPIOB_CLK_ENABLE();

    GPIO_InitStruct.Pin = SCK_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(SCK_GPIO_Port, &GPIO_InitStruct);
}

static void TWI_SCK_OPEN_DRAIN(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    __HAL_RCC_GPIOB_CLK_ENABLE();

    GPIO_InitStruct.Pin = SCK_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(SCK_GPIO_Port, &GPIO_InitStruct);
}

static void TWI_LED_H(void)
{
    HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET);
}

static void TWI_LED_L(void)
{
    HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET);
}

static void TWI_GPIO_INIT(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    __HAL_RCC_GPIOB_CLK_ENABLE();
    __HAL_RCC_GPIOA_CLK_ENABLE();
    /*Configure GPIO pins : K1_Pin K2_Pin */
    HAL_GPIO_WritePin(GPIOB, SCK_Pin | SDA_Pin, GPIO_PIN_SET);

    GPIO_InitStruct.Pin = SCK_Pin | SDA_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    HAL_GPIO_WritePin(GPIOA, LED_Pin, GPIO_PIN_SET);

    GPIO_InitStruct.Pin = LED_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = K1_Pin | K2_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}

void TWI_WrByte(unsigned char SendByte)
{
    unsigned char i = 0;
    for (i = 0; i < 8; i++)
    {
        TWI_SCK_H();
        if (SendByte & 0x80) // MSB
        {
            TWI_SDA_H();
        }
        else
        {
            TWI_SDA_L();
        }
        SendByte <<= 1;
        delay10Us(1);
        TWI_SCK_L();
        delay10Us(1);
    }
}

unsigned char TWI_RdByte(void)
{
    unsigned char i;
    unsigned char ReceiveByte = 0xff;
    for (i = 0; i < 8; i++)
    {
        TWI_SCK_H();
        ReceiveByte <<= 1;
        delay10Us(1); // I2C_delay();
        TWI_SCK_L();
        if (TWI_SDA_read())
        {
            ReceiveByte |= 0x01;
        }
        else
        {
            ReceiveByte &= 0xFE;
        }
        delay10Us(1); // I2C_delay();
    }
    return ReceiveByte;
}

unsigned char TWI_RDREG(unsigned char ReadAddress, unsigned char *pData)
{

    ReadAddress |= SUB1G_RD_CMD;
    TWI_SDA_H();
    TWI_SDA_PUSH_PULL();
    TWI_SCK_H();
    TWI_SCK_PUSH_PULL();
    TWI_WrByte(ReadAddress);
    TWI_SDA_H();
    TWI_SDA_OPEN_DRAIN();
    *pData = TWI_RdByte();
    TWI_SDA_H();
    TWI_SDA_OPEN_DRAIN();
    TWI_SCK_H();
    TWI_SCK_OPEN_DRAIN();
    return 1;
}

unsigned char TWI_WRREG(unsigned char WriteAddress, unsigned char SendByte)
{
    WriteAddress |= SUB1G_WR_CMD;
    // TWI_SDA_PUSH_PULL();
    TWI_SDA_H();
    TWI_SDA_PUSH_PULL();
    TWI_SCK_H();
    TWI_SCK_PUSH_PULL();
    TWI_WrByte(WriteAddress);
    TWI_WrByte(SendByte);
    TWI_SDA_H();
    TWI_SDA_OPEN_DRAIN();
    TWI_SCK_H();
    TWI_SCK_OPEN_DRAIN();
    return 1;
}

void TWI_RST(void)
{
    TWI_SDA_H();
    TWI_SDA_PUSH_PULL();
    TWI_SCK_H();
    TWI_SCK_PUSH_PULL();
    // DATA pin low for 32 clock cycles and clocking in 0x8D00
    TWI_WrByte(0x00);
    TWI_WrByte(0x00);
    TWI_WrByte(0x00);
    TWI_WrByte(0x00);
    TWI_WrByte(0x8D);
    TWI_WrByte(0x00);
    TWI_SCK_H();
    TWI_SCK_OPEN_DRAIN();
    TWI_SDA_H();
    TWI_SDA_OPEN_DRAIN();
}

void SOFT_RST(void)
{
    TWI_SDA_L();
    TWI_SDA_PUSH_PULL();
    TWI_SCK_H();
    TWI_SCK_PUSH_PULL();
    TWI_WrByte(0xBD);
    TWI_WrByte(0x01);
    TWI_SCK_H();
    TWI_SCK_OPEN_DRAIN();
    TWI_SDA_H();
    TWI_SDA_OPEN_DRAIN();
}

void drv_sub1g_reg_write(unsigned char regaddr, unsigned short regdat)
{
    unsigned char low_data, high_data;
    TWI_WRREG(0x18, regaddr);
    low_data = regdat % 0x100;
    high_data = regdat / 0x100;
    TWI_WRREG(0x19, low_data);
    TWI_WRREG(0x1A, high_data);
    TWI_WRREG(0x25, 0x01);
}

unsigned short drv_sub1g_reg_read(unsigned char regaddr)
{
    unsigned char low_rd, high_rd;

    TWI_WRREG(0x18, regaddr);

    TWI_RDREG(0x1B, &low_rd);
    TWI_RDREG(0x1C, &high_rd);

    return high_rd * 0x100 | low_rd;
}

static int drv_sub1g_IsExist(void)
{
    unsigned short back, dat;

    back = drv_sub1g_reg_read(0x00);
    drv_sub1g_reg_write(0x00, 0x0000);

    dat = drv_sub1g_reg_read(0x00);
    drv_sub1g_reg_write(0x00, back);

    if (0x0000 == dat)
        return 1;
    else
        return 0;
}

void drv_sub1g_send_data(unsigned char *data, unsigned int size)
{
    unsigned char SendByte;

    TWI_SDA_L();
    TWI_SDA_PUSH_PULL();
    for (int i = 0; i < size; i++)
    {
        SendByte = data[i];
        for (int k = 0; k < size; k++)
        {
            if(SendByte & 0x80)
            {
                TWI_SDA_H();
            }
            else
            {
                TWI_SDA_L();
            }
            SendByte <<= 1;
            HAL_Delay(1);
        }
    }
    TWI_SDA_H();
    TWI_SDA_OPEN_DRAIN();
}

int drv_sub1g_Init(unsigned short para[], unsigned char length) // SoftwareInit of chip
{
    unsigned char i;

    unsigned char low_data, high_data;
    unsigned char regaddr;
    unsigned short regdat;

    // step1
    TWI_RST();
    // step2
    SOFT_RST();
    HAL_Delay(1);
    // step3
    TWI_WRREG(0x02, 0x78);
    // step4
    TWI_WRREG(0x2F, 0x80);
    TWI_WRREG(0x35, 0xCA);
    TWI_WRREG(0x36, 0xEB);
    TWI_WRREG(0x37, 0x37);
    TWI_WRREG(0x38, 0x82);
    TWI_WRREG(0x12, 0x10);
    TWI_WRREG(0x12, 0x00);
    TWI_WRREG(0x24, 0x07);
    TWI_WRREG(0x1D, 0x20);
    // step5
    for (i = 0; i < length; i++) // step 6
    {
        // step5
        regaddr = i;      // set reg addr
        regdat = para[i]; // set reg data
        TWI_WRREG(0x18, regaddr);
        low_data = regdat % 0x100;
        high_data = regdat / 0x100;
        TWI_WRREG(0x19, low_data);
        TWI_WRREG(0x1A, high_data);
        TWI_WRREG(0x25, 0x01);
    }
    if (0 == drv_sub1g_IsExist())
        return 0;
    //  step6
    TWI_WRREG(0x0D, 0x02);
    // send data here
    drv_sub1g_send_data(send_data, sizeof(send_data));

    TWI_WRREG(0x02, 0x7F);
    return 1;
}

void FREQUENCY_CONFIG(void)
{
unsigned char low_data,high_data;
unsigned char regaddr;
unsigned short regdat;
unsigned char low_rd,high_rd;
// step1
TWI_RST();
// step2
SOFT_RST();
HAL_Delay(1);
// step3
TWI_WRREG(0x02, 0x78);
// step4
TWI_WRREG(0x2F, 0x80);
TWI_WRREG(0x35, 0xCA);
TWI_WRREG(0x36, 0xEB);
TWI_WRREG(0x37, 0x37);
TWI_WRREG(0x38, 0x82);
TWI_WRREG(0x12, 0x10);
TWI_WRREG(0x12, 0x00);
TWI_WRREG(0x24, 0x07);
TWI_WRREG(0x1D, 0x20);
// step5
regaddr=0x07; // set frequency reg addr
regdat=0xB81F; // set frequency reg data
TWI_WRREG(0x18, regaddr);
low_data=regdat%0x100;
high_data=regdat/0x100;
TWI_WRREG(0x19,low_data);
TWI_WRREG(0x1A,high_data);
TWI_WRREG(0x25, 0x01);
// read register
TWI_RDREG(0x1B,&low_rd);
TWI_RDREG(0x1C,&high_rd);
//if want set more reg, repeat step5
// step6
TWI_WRREG(0x0D, 0x02);
// send data here
while(1)
{
    drv_sub1g_send_data(send_data, sizeof(send_data));
    HAL_Delay(1);
}
}

void dev_sub1g_demo(void)
{
    TWI_GPIO_INIT();
    TWI_LED_L();
    HAL_Delay(100);
    TWI_LED_H();


    
    while (1)
    {
        unsigned short *cmt_eeprom;

        if (HAL_GPIO_ReadPin(K1_GPIO_Port, K1_Pin) == 0)
        {
            cmt_eeprom = (unsigned short *)CfgTbl_433;
        }
        else if (HAL_GPIO_ReadPin(K2_GPIO_Port, K2_Pin) == 0)
        {
            cmt_eeprom = (unsigned short *)CfgTbl_315;
        }
        else
        {
            continue;
        }

        TWI_LED_L();
        drv_sub1g_Init(cmt_eeprom, 21);
        
        HAL_Delay(100);
        TWI_LED_H();
        HAL_Delay(100);
    }
}
